<?php
namespace App\Wen\Utils;

use App\Jobs\TopicImgJob;
use App\Models\Posts\WxPost;
use App\Models\Posts\WxPostsTag;
use App\Models\Posts\WxTag;
use App\Models\Circle\WxCircle;
use App\Models\WxDegreeIncrement;
use App\Models\User\WxUser;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class RealtimeUtils{
    public static function get_top_posts(){
        global $__MINI_GLOBAL_TENANT_ID__;
        return Cache::remember('realtime:get_top_posts:50:'.$__MINI_GLOBAL_TENANT_ID__, 900, function () use ($__MINI_GLOBAL_TENANT_ID__){

            $neryly_post_top_degree = WxDegreeIncrement::select(DB::raw('sum(degree_increment) as degree_increment_count, object_id'))->where([['type','=', 1],['created_at', '>', now()->subHours(Settings::get('realtime_post_degree_increment_hot_num_in_hours', 3))]])->groupBy('object_id')->orderBy('degree_increment_count', 'desc')->limit(Settings::get('realtime_post_degree_increment_hot_num', 3))->pluck('degree_increment_count','object_id');
            $neayly_post_ids = array_keys($neryly_post_top_degree->toArray());

            $not_normal_posts_id = [];
            $top_post_ids = [];
            $posts = WxPost::where('degree', '>', 0)->orderBy('degree', 'desc')->orderBy('id', 'desc')->where('tenant_id', $__MINI_GLOBAL_TENANT_ID__)->get(['id', 'posts_title', 'posts_content', 'posts_state','is_examine'])->map(function ($v) use ($neayly_post_ids, &$not_normal_posts_id, &$top_post_ids){
                if(in_array($v->id, $neayly_post_ids)){
                    $v->is_hot = 1;
                }else{
                    $v->is_hot = 0;
                }
                if($v->posts_state != 0 || $v->is_examine != 1){
                    $not_normal_posts_id[] = $v->id;
                }else{
                    $top_post_ids[] = $v->id;
                }
                $posts_content_raw = preg_replace("/<(img|video).*?src[^\'\"]+[\'\"]([^\"\']+)[^>]+>/is", '',$v->posts_content);
                $posts_content_raw =trim_all_space(strip_tags(html_entity_decode(_mini_phone( _mini_aite_replace( _mini_emoji($posts_content_raw, true) , true), true))), true);
                $v->posts_content = $v->posts_title ?: PostUtils::get_the_title($posts_content_raw, $v->id);
                return $v;
            })->filter(function ($v) {
                return ($v->posts_state == 0 && $v->is_examine == 1);
            });

            if($not_normal_posts_id){
                WxDegreeIncrement::whereIn('object_id', $not_normal_posts_id)->where('type',1)->delete();
            }

            $shows_top = Settings::get('realtime_post_list_shows_top', 10);
            if($top_post_ids && $shows_top > 0) {
                $cache_true_top_map = [];
                if (count($top_post_ids) > $shows_top) {
                    $cache_ids = array_slice($top_post_ids, 0, $shows_top);
                    $i = 1;
                    foreach ($cache_ids as $post_id) {
                        $cache_true_top_map[$post_id] = $i;
                        $i++;
                    }
                } else {
                    $cache_ids = $top_post_ids;
                    $i = 1;
                    foreach ($cache_ids as $post_id) {
                        $cache_true_top_map[$post_id] = $i;
                        $i++;
                    }
                }
                if ($cache_true_top_map) {
                    Cache::forget('realtime:posts:show_top:ids');
                    Cache::put('realtime:posts:show_top:ids', json_encode($cache_true_top_map), 900);
                }
            }

            if($posts){
                return ['posts'=>$posts->toArray(), 'update_time'=>current_time()];
            }
            return [];
        });
    }

    public static function get_topic_top(){
        return Cache::remember('realtime:get_top_topics:50', 900, function (){
            $topic_top_degree = WxDegreeIncrement::select(DB::raw('sum(degree_increment) as degree_increment_count, object_id'))->where('type', 5)->groupBy('object_id')->orderBy('degree_increment_count', 'desc')->limit(60)->pluck('degree_increment_count','object_id');
            if($topic_top_degree){
                $neryly_topic_top_degree = WxDegreeIncrement::select(DB::raw('sum(degree_increment) as degree_increment_count, object_id'))->where([['type','=', 5],['created_at', '>', now()->subHours(Settings::get('realtime_topic_degree_increment_hot_num_in_hours', 3))]])->groupBy('object_id')->orderBy('degree_increment_count', 'desc')->limit(Settings::get('realtime_topic_degree_increment_hot_num', 3))->pluck('degree_increment_count','object_id');
                $neayly_topic_ids = array_keys($neryly_topic_top_degree->toArray());
                $top_topic_ids = array_keys($topic_top_degree->toArray());

                $not_normal_topicss_id = [];
                $tags = WxTag::whereIn('id', $top_topic_ids)->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $top_topic_ids) . '"' . ")"))->get(['id','tags_name', 'head_portrait','tags_state'])->map(function ($v) use ($neayly_topic_ids, &$not_normal_topicss_id){
                    if(in_array($v->id, $neayly_topic_ids)){
                        $v->is_hot = 1;
                    }else{
                        $v->is_hot = 0;
                    }
                    if($v->is_hot == 0){
                        $v->tags_number = WxPostsTag::where('tags_id', $v->id)->count();
                        $v->degree = WxDegreeIncrement::where([['type', '=', 5], ['object_id', '=', $v->id]])->sum('degree_increment');
                    }else{
                        $v->tags_number = 0;
                        $v->degree = WxDegreeIncrement::where([['type', '=', 5], ['object_id', '=', $v->id]])->sum('degree_increment');
                    }
                    if($v->tags_state != 0){
                        $not_normal_topicss_id[] = $v->id;
                    }
                    if(_empty_($v->head_portrait)){
                        $v->head_portrait = Settings::get('img_default_topic_avatar');
                        TopicImgJob::dispatch($v->id);
                    }
                    return $v;
                })->filter(function ($v) {
                    return $v->tags_state == 0;
                });

                if($not_normal_topicss_id){
                    WxDegreeIncrement::whereIn('object_id', $not_normal_topicss_id)->where('type',5)->delete();
                }

                if($tags){
                    return ['topics'=>$tags->toArray(), 'update_time'=>current_time()];
                }
            }
            return [];
        });
    }

    public static function get_user_top(){
        global $__MINI_GLOBAL_TENANT_ID__;
        return Cache::remember('realtime:get_user_top:50:'.$__MINI_GLOBAL_TENANT_ID__, 900, function () use ($__MINI_GLOBAL_TENANT_ID__){
            $user_top_degree = WxDegreeIncrement::select(DB::raw('sum(degree_increment) as degree_increment_count, object_id'))->where('type', 4)->groupBy('object_id')->orderBy('degree_increment_count', 'desc')->limit(60)->pluck('degree_increment_count','object_id');
            if($user_top_degree){
                $neryly_user_top_degree = WxDegreeIncrement::select(DB::raw('sum(degree_increment) as degree_increment_count, object_id'))->where([['type','=', 4],['created_at', '>', now()->subHours(Settings::get('realtime_user_degree_increment_hot_num_in_hours', 3))]])->groupBy('object_id')->orderBy('degree_increment_count', 'desc')->limit(Settings::get('realtime_user_degree_increment_hot_num', 3))->pluck('degree_increment_count','object_id');
                $neayly_user_ids = array_keys($neryly_user_top_degree->toArray());
                $top_user_ids = array_keys($user_top_degree->toArray());

                $not_normal_users_id = [];
                $users = WxUser::whereIn('id', $top_user_ids)->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $top_user_ids) . '"' . ")"))->where('tenant_id', $__MINI_GLOBAL_TENANT_ID__)->get(['id', 'user_name', 'user_avatar', 'user_state'])->map(function ($v) use ($neayly_user_ids, &$not_normal_users_id){
                    if(in_array($v->id, $neayly_user_ids)){
                        $v->is_hot = 1;
                    }else{
                        $v->is_hot = 0;
                    }
                    $v->degree = WxDegreeIncrement::where([['type', '=', 4], ['object_id', '=', $v->id]])->sum('degree_increment');
                    if($v->user_state != 0){
                        $not_normal_users_id[] = $v->id;
                    }
                    if(_empty_($v->head_portrait)){
                        $v->head_portrait = Settings::get('img_default_avatar');
                    }
                    return $v;
                })->filter(function ($v) {
                    return $v->user_state == 0;
                });

                if($not_normal_users_id){
                    WxDegreeIncrement::whereIn('object_id', $not_normal_users_id)->where('type',4)->delete();
                }

                if($users){
                    return ['users'=>$users->toArray(), 'update_time'=>current_time()];
                }
            }
            return [];
        });
    }

    public static function get_circle_top(){
        global $__MINI_GLOBAL_TENANT_ID__;
        return Cache::remember('realtime:get_circle_top:50:'.$__MINI_GLOBAL_TENANT_ID__, 900, function () use ($__MINI_GLOBAL_TENANT_ID__){
            $circle_top_degree = WxDegreeIncrement::select(DB::raw('sum(degree_increment) as degree_increment_count, object_id'))->where('type', 2)->groupBy('object_id')->orderBy('degree_increment_count', 'desc')->limit(60)->pluck('degree_increment_count','object_id');
            if($circle_top_degree){
                $neryly_circle_top_degree = WxDegreeIncrement::select(DB::raw('sum(degree_increment) as degree_increment_count, object_id'))->where([['type','=', 2],['created_at', '>', now()->subHours(Settings::get('realtime_circle_degree_increment_hot_num_in_hours', 3))]])->groupBy('object_id')->orderBy('degree_increment_count', 'desc')->limit(Settings::get('realtime_circle_degree_increment_hot_num', 3))->pluck('degree_increment_count','object_id');
                $neayly_circle_ids = array_keys($neryly_circle_top_degree->toArray());
                $top_circle_ids = array_keys($circle_top_degree->toArray());

                $not_normal_circle_id = [];
                $circles = WxCircle::whereIn('id', $top_circle_ids)->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $top_circle_ids) . '"' . ")"))->where('tenant_id', $__MINI_GLOBAL_TENANT_ID__)->get(['id', 'circle_name', 'head_portrait', 'circle_state'])->map(function ($v) use ($neayly_circle_ids, &$not_normal_circle_id){
                    if(in_array($v->id, $neayly_circle_ids)){
                        $v->is_hot = 1;
                    }else{
                        $v->is_hot = 0;
                    }
                    $v->degree = WxDegreeIncrement::where([['type', '=', 2], ['object_id', '=', $v->id]])->sum('degree_increment');
                    if($v->circle_state != 1){
                        $not_normal_circle_id[] = $v->id;
                    }
                    if(_empty_($v->head_portrait)){
                        $v->head_portrait = Settings::get('img_default_avatar');
                    }
                    return $v;
                })->filter(function ($v) {
                    return $v->circle_state == 1;
                });

                if($not_normal_circle_id){
                    WxDegreeIncrement::whereIn('object_id', $not_normal_circle_id)->where('type',2)->delete();
                }

                if($circles){
                    return ['circles'=>$circles->toArray(), 'update_time'=>current_time()];
                }
            }
            return [];
        });
    }

    /**
     * @param $object_id
     * @param $type （1:笔记 2:圈子 3:商品 4:用户 5:话题）
     * @param int $degree
     */
    public static function add_object_degree($object_id, $type, $degree = 1){
        if(_empty_($object_id) || _empty_($type)){
            return null;
        }
        if(in_array($type, [1,2,3,4,5])){
            // 计算增量
            $increment_obj = new WxDegreeIncrement();
            $increment_obj->object_id = $object_id;
            $increment_obj->type = $type;
            $increment_obj->degree_increment = $degree;
            return $increment_obj->save();
        }
        return null;
    }



}
